Skip to content

feat(protos)!: remove deprecated IntervalDayToSecond.microseconds field#1116

Open
nielspardon wants to merge 1 commit into
substrait-io:mainfrom
nielspardon:feat/remove-deprecated-interval-microseconds
Open

feat(protos)!: remove deprecated IntervalDayToSecond.microseconds field#1116
nielspardon wants to merge 1 commit into
substrait-io:mainfrom
nielspardon:feat/remove-deprecated-interval-microseconds

Conversation

@nielspardon

@nielspardon nielspardon commented Jul 2, 2026

Copy link
Copy Markdown
Member

Summary

Removes the deprecated microseconds field (field 3) from Expression.Literal.IntervalDayToSecond. It was deprecated in #665 (first released in v0.54.0, 2024-08-11 — ~2 years ago) in favor of precision (field 4) + subseconds (field 5). Field number 3 and the name microseconds are reserved to prevent reuse.

With microseconds gone, the precision_mode oneof has only one remaining member, so this PR dissolves the oneof and makes precision a plain int32, matching how every other precision-bearing type (PrecisionTimestamp, PrecisionTimestampTZ, PrecisionTime, IntervalCompound) declares precision.

     message IntervalDayToSecond {
+      reserved 3; // formerly the deprecated microseconds field, replaced by precision and subseconds
+      reserved "microseconds";
+
       int32 days = 1;
       int32 seconds = 2;
-      oneof precision_mode {
-        int32 microseconds = 3 [deprecated = true];
-        int32 precision = 4;
-      }
+      int32 precision = 4;
       int64 subseconds = 5;
     }

Wire compatibility

This is wire compatible:

  • precision keeps field number 4 and subseconds keeps field number 5.
  • oneof members are encoded identically to plain fields on the wire, so dissolving the oneof changes nothing on the wire.
  • An old plan that still carries microseconds (field 3) is treated as an unknown field by consumers built against the new schema rather than failing to parse.

It is source-breaking for generated bindings (removes the microseconds accessor and the precision_mode/PrecisionModeCase wrapper), and semantically breaking: consumers can no longer interpret legacy plans that encoded sub-second values via microseconds without an explicit precision.

SDK impact analysis

Analyzed all four SDKs before proposing removal:

SDK Uses deprecated microseconds? Migrated to precision/subseconds? Impact
go Read path only (backcompat) Yes — all writes use new fields Source-breaking: a couple of read branches to drop
java One read-path fallback (ProtoExpressionConverter) Yes — all writes use new fields Source-breaking: one line to drop
rust No N/A — prost regenerates from proto None
python No Yes None

No SDK produces microseconds; all are functionally on precision/subseconds. The go and java changes are trivial companion cleanups on their read/backcompat paths.

Notes

  • Overlaps with the in-flight interval-precision PR (b6398cc, "require explicit interval precision and allow picoseconds"), which touches the same lines — a rebase/conflict resolution will be needed depending on merge order.

BREAKING CHANGE: removes deprecated Expression.Literal.IntervalDayToSecond.microseconds field. Producers must set precision + subseconds. Consumers can no longer interpret legacy plans that encoded sub-second values via microseconds without an explicit precision.

🤖 Generated with AI


This change is Reviewable

@nielspardon nielspardon marked this pull request as ready for review July 2, 2026 12:32
The microseconds field (field 3) of Expression.Literal.IntervalDayToSecond
was deprecated in favor of the precision + subseconds fields, which cover
and replace it. Remove it and reserve field number 3 (and the name) to
prevent reuse.

With microseconds gone, the precision_mode oneof has a single remaining
member, so dissolve it and make precision a plain int32 field, matching
how every other precision-bearing type (PrecisionTimestamp,
PrecisionTimestampTZ, PrecisionTime, IntervalCompound) declares precision.

This is wire compatible: precision keeps field number 4 and subseconds
keeps field number 5, and oneof members are encoded identically to plain
fields on the wire. An old plan that still carries microseconds (field 3)
will be treated as an unknown field by consumers built against the new
schema rather than failing to parse.

Analyzed the four Substrait SDKs before removal:
- go: reads microseconds only for backward compatibility; already writes
  precision/subseconds. Source-breaking (a couple of read branches to drop).
- java: one backward-compat read fallback (ProtoExpressionConverter);
  already writes precision/subseconds. Source-breaking (one line to drop).
- rust: no hand-written use; prost regenerates from the proto. No break.
- python: no use of the deprecated field; already on precision/subseconds.
  No break.

BREAKING CHANGE: removes deprecated Expression.Literal.IntervalDayToSecond.microseconds
field. Producers must set precision + subseconds. Consumers can no longer
interpret legacy plans that encoded sub-second values via microseconds
without an explicit precision.
@nielspardon nielspardon force-pushed the feat/remove-deprecated-interval-microseconds branch from 52573ab to ff72aef Compare July 9, 2026 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant